package com.md.common.exception;

import com.md.common.utils.validate.BeanValidator;
import com.md.common.utils.validate.ValidateResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.List;


/**
 * 功能描述：通用的业务数据校验工具
 *
 * @author lujianping@oak168.com
 * @version 1.0
 * @date 2018-6-14 11:51
 * @since JDK 1.8
 */
public class BizDataValidUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(BizDataValidUtil.class);

    /**
     * 反射构建业务异常实例
     *
     * @param bexClazz  实际业务异常类型
     * @param errorCode 错误码
     * @return 异常实例
     */
    public static BaseBizException createBizException(Class<? extends BaseBizException> bexClazz, int errorCode) {
        BaseBizException bex = null;
        Object[] args = {errorCode, null};
        Class[] argClazz = {int.class, Object[].class};
        try {
            Constructor bexConstructor = bexClazz.getDeclaredConstructor(argClazz);
            bex = (BaseBizException) bexConstructor.newInstance(args);
        } catch (NoSuchMethodException e) {
            LOGGER.error("反射实例化业务异常类对象发生NoSuchMethodException异常，message:{}", e.getMessage(), e);
        } catch (InstantiationException e) {
            LOGGER.error("反射实例化业务异常类对象发生InstantiationException异常，message:{}", e.getMessage(), e);
        } catch (IllegalAccessException e) {
            LOGGER.error("反射实例化业务异常类对象发生IllegalAccessException异常，message:{}", e.getMessage(), e);
        } catch (InvocationTargetException e) {
            LOGGER.error("反射实例化业务异常类对象发生InvocationTargetException异常，message:{}", e.getMessage(), e);
        }
        return bex;
    }

    /**
     * 反射构建业务异常实例
     *
     * @param bexClazz  实际业务异常类型
     * @param errorCode 错误码
     * @return 异常实例
     */
    public static BaseBizException createBizException(Class<? extends BaseBizException> bexClazz, int errorCode, String eerorMsg) {
        BaseBizException bex = null;
        Object[] args = {errorCode, eerorMsg, null};
        Class[] argClazz = {int.class, String.class, Object[].class};
        try {
            Constructor bexConstructor = bexClazz.getDeclaredConstructor(argClazz);
            bex = (BaseBizException) bexConstructor.newInstance(args);
        } catch (NoSuchMethodException e) {
            LOGGER.error("反射实例化业务异常类对象发生NoSuchMethodException异常，message:{}", e.getMessage(), e);
        } catch (InstantiationException e) {
            LOGGER.error("反射实例化业务异常类对象发生InstantiationException异常，message:{}", e.getMessage(), e);
        } catch (IllegalAccessException e) {
            LOGGER.error("反射实例化业务异常类对象发生IllegalAccessException异常，message:{}", e.getMessage(), e);
        } catch (InvocationTargetException e) {
            LOGGER.error("反射实例化业务异常类对象发生InvocationTargetException异常，message:{}", e.getMessage(), e);
        }
        return bex;
    }

    /**
     * 校验字符不为空
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertStrNotEmpty(String data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (StringUtils.isEmpty(data)) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验字符不为空
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertStrEquals(String a, String b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || a.equals("") || b == null || b.equals("")) {
            throw createBizException(bexClazz, errorCode);
        }
        if (!a.equals(b)) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验字符不为空
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertStrNotEquals(String a, String b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || a.equals("") || b == null || b.equals("")) {
            throw createBizException(bexClazz, errorCode);
        }
        if (a.equals(b)) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验对象不为空
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws BaseBizException
     */
    public static void assertObjNotNull(Object data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (data == null) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验对象为空
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertObjNull(Object data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (data != null) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验对象为空
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static <T> void assertListEmpty(List<T> data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (!CollectionUtils.isEmpty(data)) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验对象不为空
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static <T> void assertListNotEmpty(List<T> data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (CollectionUtils.isEmpty(data)) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验对象不为空
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static <T> void assertArrayNotEmpty(Object[] data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (data == null || data.length == 0) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验对象为true
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertTrue(boolean data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (!data) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验对象为false
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertFalse(boolean data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (data) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验int为正整数
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertPositInt(Integer data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (data == null || data <= 0) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验int为正整数
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertIntNotNull(Integer data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (data == null) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验long为正整数
     *
     * @param data
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertPositLong(Long data, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (data == null || data <= 0) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验整数相等
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertIntEquals(Integer a, Integer b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || b == null) {
            throw createBizException(bexClazz, errorCode);
        }
        if (a.intValue() != b) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验整数不相等
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertIntNotEquals(Integer a, Integer b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || b == null) {
            throw createBizException(bexClazz, errorCode);
        }
        if (a.intValue() == b) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验整数大于
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertIntGt(Integer a, Integer b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || b == null) {
            throw createBizException(bexClazz, errorCode);
        }
        if (a.longValue() <= b) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验整数区间
     *
     * @param min 最小值
     * @param max 最大值
     * @param a   比较数
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertIntBetween(Integer min, Integer max, Integer a, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if(min == null || max == null || a == null){
            throw createBizException(bexClazz, errorCode);
        }
        if( a < min || a > max){
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验整数大于
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertLongGt(Long a, Long b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || b == null) {
            throw createBizException(bexClazz, errorCode);
        }
        if (a.longValue() <= b) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验整数大于等于
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertLongGteq(Long a, Long b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || b == null) {
            throw createBizException(bexClazz, errorCode);
        }
        if (a.longValue() < b) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验小数大于
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertBigDecimalGt(BigDecimal a, BigDecimal b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || b == null) {
            throw createBizException(bexClazz, errorCode);
        }
        if (a.compareTo(b) <= 0) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验小数大于等于
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertBigDecimalGtEq(BigDecimal a, BigDecimal b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || b == null) {
            throw createBizException(bexClazz, errorCode);
        }
        if (a.compareTo(b) < 0) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验两个字符串忽略大小写是否匹配
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertEqualsIgnoreCase(String a, String b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || b == null) {
            throw createBizException(bexClazz, errorCode);
        }
        if (!a.equalsIgnoreCase(b)) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验两个字符串是否匹配
     *
     * @param a
     * @param b
     * @param bexClazz
     * @param errorCode
     * @throws Exception
     */
    public static void assertEquals(String a, String b, Class<? extends BaseBizException> bexClazz, int errorCode) throws BaseBizException {
        if (a == null || b == null) {
            throw createBizException(bexClazz, errorCode);
        }
        if (!a.equals(b)) {
            throw createBizException(bexClazz, errorCode);
        }
    }

    /**
     * 校验bean
     * @param obj
     * @param bexClazz
     * @param groupValidator
     * @param <T>
     * @throws BaseBizException
     */
    public static <T> void validateBean(T obj, Class<? extends BaseBizException> bexClazz, Object... groupValidator) throws BaseBizException {
        ValidateResult validateResult = BeanValidator.validate(obj, groupValidator);
        if(validateResult.isHasErrors()){
            throw createBizException(bexClazz, validateResult.getErrorCode(), validateResult.getErrorMsg());
        }
    }
}
